#include "funddbspider.h"

#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>

static const QString fundDBUrl = "https://api.jiucaishuo.com/v2/fund-lists/ssjz";

FundDBSpider::FundDBSpider(QObject *parent) : QObject(parent)
{
    clear();
    accessManger = new QNetworkAccessManager(this);
    QObject::connect(accessManger, SIGNAL(finished(QNetworkReply*)), this, SLOT(requestFinished(QNetworkReply*)));
}

FundDBSpider::~FundDBSpider() {
    accessManger->deleteLater();
}

void FundDBSpider::clear() {
    valuationList.clear();
    valuationString = "";
    valuationTimestamp = 0;
}

void FundDBSpider::ask(QString code) {
//    qDebug() << QSslSocket::supportsSsl();
//    qDebug() << QSslSocket::sslLibraryBuildVersionString();
    qDebug() << "fundb ask: " + code;
    // Clear data first
    clear();
    // Net request part
    QNetworkRequest request;
//    QNetworkAccessManager* accessManger = new QNetworkAccessManager(this);
    QObject::connect(accessManger, SIGNAL(finished(QNetworkReply*)), this, SLOT(requestFinished(QNetworkReply*)));
    // Set header
    request.setUrl(QUrl(fundDBUrl));
    request.setRawHeader("accept", "application/json, text/plain, */*");
//    request.setRawHeader("accept-encoding", "gzip, deflate, br");
    request.setRawHeader("accept-language", "zh-CN,zh-TW;q=0.9,zh;q=0.8,en;q=0.7");
    request.setRawHeader("origin", "https://funddb.cn");
    request.setRawHeader("Content-Type", "application/x-www-form-urlencoded");
    //    request.setRawHeader("content-type", "application/json;charset=UTF-8");
    QByteArray postArray;
    postArray.append("code=" + code);
    accessManger->post(request, postArray);
}

void FundDBSpider::requestFinished(QNetworkReply *reply) {
    QVariant statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
    if(!statusCode.isValid()) {
        emit finished(false);
        return;
    }

    QVariant reason = reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString();
    if(!reason.isValid()) {
        qDebug() << "status code=" << statusCode.toInt();
        emit finished(false);
        return;
    }

    QNetworkReply::NetworkError err = reply->error();
    if(err != QNetworkReply::NoError) {
        qDebug() << "Failed: " << reply->errorString();
        qDebug() << "reason=" << reason.toString();
        emit finished(false);
    } else {
        QByteArray bytes = reply->readAll();
        if(bytes.size() == 0) {
            emit finished(false);
            return;
        }
        QString string = QString::fromUtf8(bytes).simplified();
        analyze(string);
    }
    reply->deleteLater();
}

void FundDBSpider::analyze(QString str) {
    QJsonParseError jsonError;
    QByteArray jsonArray = str.toUtf8();
    QJsonDocument  jsonDoucment = QJsonDocument::fromJson(jsonArray, &jsonError);
    if(jsonError.error != QJsonParseError::NoError) {
        qDebug() << "FundDB get json data failed: " + str;
        emit finished(false);
        return;
    }

    QJsonObject jsonRootObj = jsonDoucment.object();
    QJsonObject jsonRootDataObj = jsonRootObj.value("data").toObject();
    QJsonValue seriesValue = jsonRootDataObj.value("series");
    if(!seriesValue.isArray()) {
        qDebug() << "FundDB get series array failed";
        emit finished(false);
        return;
    }
    if(1 != seriesValue.toArray().size()) {
        qDebug() << "FundDB series length error";
        emit finished(false);
//        qDebug() << "FundDBSpider::analyze: " << str;
        return;
    }

    QJsonObject seriesObj = seriesValue.toArray().at(0).toObject();
    QJsonValue dataValue = seriesObj.value("data");
    if(!dataValue.isArray()) {
        qDebug() << "FundDB get data array failed";
        emit finished(false);
        return;
    } else {
        QJsonArray valuationArray;
        QJsonArray dataArray = dataValue.toArray();
        for(int i = 0; i < dataArray.size(); i++) {
            QJsonArray valueArray = dataArray.at(i).toArray();
            if(valueArray.size() > 3) {
                QJsonArray singleArray;
                valuationData_t singleData;

                if(valueArray.at(0).isDouble()) {
                    singleData.timestamp = valueArray.at(0).toInt();
                } else if(valueArray.at(0).isString()) {
                    singleData.timestamp = valueArray.at(0).toString().toInt();
                } else {
                    qDebug() << "Get timestamp failed";
                }
                singleData.rate = valueArray.at(1).toDouble();
                singleData.valuation = valueArray.at(2).toString().toDouble();
                valuationList.append(singleData);

                singleArray.append(QString::number(singleData.timestamp));
                singleArray.append(QString::number(singleData.rate, 'f', 4));
                singleArray.append(QString::number(singleData.valuation, 'f', 4));
                valuationArray.append(singleArray);
            }
        }
        QJsonDocument valuation_Document;
        valuation_Document.setArray(valuationArray);
        valuationString = QString::fromUtf8(valuation_Document.toJson(QJsonDocument::Compact).constData());
        valuationTimestamp = QDateTime::currentDateTime().toTime_t();

        emit finished(true);
    }
}

QString FundDBSpider::getString() {
    return valuationString;
}

QList<valuationData_t> FundDBSpider::getList() {
    return valuationList;
}

int FundDBSpider::getTimestamp() {
    return valuationTimestamp;
}
